package com.mb.ext.core.dao.impl.group;

import java.util.ArrayList;
import java.util.List;

import javax.persistence.NoResultException;
import javax.persistence.TypedQuery;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Repository;

import com.mb.ext.core.dao.AbstractBaseDAO;
import com.mb.ext.core.dao.group.GroupBuyProductDAO;
import com.mb.ext.core.entity.group.GroupBuyProductEntity;
import com.mb.ext.core.entity.merchant.MerchantEntity;
import com.mb.ext.core.service.spec.ProductSearchDTO;
import com.mb.framework.exception.DAOException;
import com.mb.framework.util.log.LogHelper;

@Repository("groupBuyProductDAO")
@Qualifier("groupBuyProductDAO")
public class GroupBuyProductDAOImpl extends AbstractBaseDAO<GroupBuyProductEntity> implements GroupBuyProductDAO {
	private final LogHelper logger = LogHelper.getInstance(this.getClass().getName());

	/**
	 * Initializing Entity.
	 */
	public GroupBuyProductDAOImpl() {
		super();
		this.setEntityClass(GroupBuyProductEntity.class);
	}

	@Override
	public void addGroupBuy(GroupBuyProductEntity groupBuyProductEntity) throws DAOException {

		this.save(groupBuyProductEntity);

	}

	@Override
	public void updateGroupBuy(GroupBuyProductEntity groupBuyProductEntity) throws DAOException {

		this.update(groupBuyProductEntity);

	}

	@Override
	public void deleteGroupBuy(GroupBuyProductEntity groupBuyProductEntity) throws DAOException {

		this.delete(groupBuyProductEntity);

	}

	@Override
	public GroupBuyProductEntity getGroupBuyByUuid(String uuid) throws DAOException {
		GroupBuyProductEntity groupBuyProductEntity = null;
		try {
			groupBuyProductEntity = (GroupBuyProductEntity) em.createQuery(
					"select b from GroupBuyProductEntity b where  b.groupBuyProductUuid = :UUID and b.isDeleted=:isDeleted",
					GroupBuyProductEntity.class).setParameter("UUID", uuid).setParameter("isDeleted", Boolean.FALSE)
					.getSingleResult();
		} catch (NoResultException e) {
			logger.info("No record found for product : " + uuid);
		}
		return groupBuyProductEntity;
	}

	@Override
	public List<GroupBuyProductEntity> getBeingGroupBuyProducts() throws DAOException {
		List<GroupBuyProductEntity> groupBuyProductEntityList = new ArrayList<GroupBuyProductEntity>();
		try {
			groupBuyProductEntityList = em.createQuery(
					"select b from GroupBuyProductEntity b where b.groupBuyDefEntity.status = :STATUS and b.groupBuyDefEntity.startTime < CURRENT_TIME() and b.groupBuyDefEntity.endTime > CURRENT_TIME() and b.isDeleted=:isDeleted order by b.createDate desc",
					GroupBuyProductEntity.class)
					.setParameter("STATUS", "1")
					.setParameter("isDeleted", Boolean.FALSE).getResultList();
		} catch (NoResultException e) {
			logger.info("No record found for group buy");
		}
		return groupBuyProductEntityList;
	}

	@Override
	public List<GroupBuyProductEntity> getComingGroupBuyProducts() throws DAOException {
		List<GroupBuyProductEntity> groupBuyProductEntityList = new ArrayList<GroupBuyProductEntity>();
		try {
			groupBuyProductEntityList = em.createQuery(
					"select b from GroupBuyProductEntity b where b.groupBuyDefEntity.status = :STATUS and b.groupBuyDefEntity.startTime > CURRENT_TIME() and b.isDeleted=:isDeleted order by b.createDate desc",
					GroupBuyProductEntity.class)
					.setParameter("STATUS", "1")
					.setParameter("isDeleted", Boolean.FALSE).getResultList();
		} catch (NoResultException e) {
			logger.info("No record found for group buy");
		}
		return groupBuyProductEntityList;
	}

	@Override
	public List<GroupBuyProductEntity> getAllGroupBuyProducts() throws DAOException {
		List<GroupBuyProductEntity> groupBuyProductEntityList = new ArrayList<GroupBuyProductEntity>();
		try {
			groupBuyProductEntityList = em.createQuery(
					"select b from GroupBuyProductEntity b where b.groupBuyDefEntity.status = :STATUS and b.isDeleted=:isDeleted order by b.createDate desc",
					GroupBuyProductEntity.class)
					.setParameter("STATUS", "1")
					.setParameter("isDeleted", Boolean.FALSE).getResultList();
		} catch (NoResultException e) {
			logger.info("No record found for group buy");
		}
		return groupBuyProductEntityList;
	}

	@Override
	public List<GroupBuyProductEntity> getGroupBuysByMerchant(MerchantEntity merchantEntity) throws DAOException {
		List<GroupBuyProductEntity> groupBuyProductEntityList = new ArrayList<GroupBuyProductEntity>();
		try {
			groupBuyProductEntityList = em.createQuery("select b from GroupBuyProductEntity b where b.merchantEntity.merchantUuid = :MERCHANTUUID and b.isDeleted=:isDeleted order by b.createDate desc",GroupBuyProductEntity.class)
					.setParameter("MERCHANTUUID", merchantEntity.getMerchantUuid())
					.setParameter("isDeleted", Boolean.FALSE)
					.getResultList();
		} catch (NoResultException e) {
			logger.info("No record found for group buy");
		}
		return groupBuyProductEntityList;
	}

	@Override
	public void decrStock(String groupBuyProductUuid) throws DAOException {
		try {
			String nativeSql = "update group_buy_product set stock = stock - 1 where group_buy_product_uuid = '" + groupBuyProductUuid + "'";
			em.createNativeQuery(nativeSql).executeUpdate();
		} catch (Exception e) {
			throw new DAOException("更新团购商品库存失败");
		}


	}

	@Override
	public List<GroupBuyProductEntity> searchGroupBuyProduct(ProductSearchDTO productSearchDTO) throws DAOException {

		List<GroupBuyProductEntity> productEntityList = new ArrayList<GroupBuyProductEntity>();
		String query = "select b from GroupBuyProductEntity b where b.isDeleted=:isDeleted";
		String[] keyArray = productSearchDTO.getKeyArray();
		for (int i = 0; i < keyArray.length; i++) {
			String key = keyArray[i];
			if (ProductSearchDTO.KEY_PRODUCT_NAME.equals(key)) {
				query = query + " and b.productEntity.productName like :PRODUCTNAME";
			} else if (ProductSearchDTO.KEY_MERCHANT.equals(key)) {
				query = query + " and b.productEntity.merchantEntity.merchantUuid = :MERCHANTUUID";
			} else if (ProductSearchDTO.KEY_PRODUCT_CATE.equals(key)) {
				query = query + " and (b.productEntity.productCateEntity.productCateUuid = :PRODUCTCATEUUID or b.productEntity.productCateEntity.parentCateEntity.productCateUuid = :PRODUCTCATEUUID)";
			} else if (ProductSearchDTO.KEY_SUPPLIER.equals(key)) {
				query = query + " and b.productEntity.supplierEntity.supplierUuid = :SUPPLIERUUID";
			} else if (ProductSearchDTO.KEY_BRAND.equals(key)) {
				query = query + " and b.productEntity.productBrandEntity.productBrandUuid = :PRODUCTBRANDUUID";
			} else if (ProductSearchDTO.KEY_HOT.equals(key)) {
				query = query + " and b.productEntity.isHot = :ISHOT";
			} else if (ProductSearchDTO.KEY_NEW.equals(key)) {
				query = query + " and b.productEntity.isNew = :ISNEW";
			} else if (ProductSearchDTO.KEY_RECOMMEND.equals(key)) {
				query = query + " and b.productEntity.isRecommend = :ISRECOMMEND";
			} else if (ProductSearchDTO.KEY_ON_SALE.equals(key)) {
				query = query + " and b.productEntity.isOnSale = :ISONSALE";
			} else if (ProductSearchDTO.KEY_INVENTORY.equals(key)) {
				query = query + " and b.productEntity.totalUnit <= :INVENTORY";
			} else if (ProductSearchDTO.KEY_UNIT_POINT.equals(key)) {
				query = query + " and b.productEntity.unitPoint >= :UNITPOINTSTART";
				query = query + " and b.productEntity.unitPoint <= :UNITPOINTEND";
			} else if (ProductSearchDTO.KEY_CATE_NAME.equals(key)) {
				query = query + " and b.productEntity.productCateEntity.cateName = :CATENAME" ;
			} else if (ProductSearchDTO.KEY_GROUP_BUY_DEF.equals(key)) {
				query = query + " and b.groupBuyDefEntity.groupBuyDefUuid = :GROUPBUYDEFUUID";
			} else if (ProductSearchDTO.KEY_GROUP_BUY_STATUS_BEING.equals(key)) {
				query = query + " and b.groupBuyDefEntity.status = '1' and b.groupBuyDefEntity.startTime < CURRENT_TIME() and b.groupBuyDefEntity.endTime > CURRENT_TIME()";
			} else if (ProductSearchDTO.KEY_GROUP_BUY_STATUS_COMPLETED.equals(key)) {
				query = query + " and b.groupBuyDefEntity.status = '1' and b.groupBuyDefEntity.endTime < CURRENT_TIME()";
			} else if (ProductSearchDTO.KEY_GROUP_BUY_STATUS_NOT_STARTED.equals(key)) {
				query = query + " and b.groupBuyDefEntity.status = '1' and b.groupBuyDefEntity.startTime > CURRENT_TIME()";
			} else if (ProductSearchDTO.KEY_GROUP_BUY_STATUS_NOT_COMPLETED.equals(key)) {
				query = query + " and b.groupBuyDefEntity.status = '1' and b.groupBuyDefEntity.endTime > CURRENT_TIME()";
			}
		}
		if(!StringUtils.isEmpty(productSearchDTO.getSortBy())) {
			query = query + " order by b."+productSearchDTO.getSortBy()+" "+productSearchDTO.getSort()+"";
		}else {
			query = query + " order by b.createDate desc";
		}
		try {
			TypedQuery typedQuery = em.createQuery(query, GroupBuyProductEntity.class);
			for (int i = 0; i < keyArray.length; i++) {
				String key = keyArray[i];
				if (ProductSearchDTO.KEY_PRODUCT_NAME.equals(key)) {
					typedQuery.setParameter("PRODUCTNAME",
							"%" + productSearchDTO.getProductName() + "%");
				} else if (ProductSearchDTO.KEY_MERCHANT.equals(key)) {
					typedQuery.setParameter("MERCHANTUUID",
							productSearchDTO.getMerchantUuid());
				} else if (ProductSearchDTO.KEY_PRODUCT_CATE.equals(key)) {
					typedQuery.setParameter("PRODUCTCATEUUID",
							productSearchDTO.getProductCateUuid());
				} else if (ProductSearchDTO.KEY_SUPPLIER.equals(key)) {
					typedQuery.setParameter("SUPPLIERUUID",
							productSearchDTO.getSupplierUuid());
				} else if (ProductSearchDTO.KEY_BRAND.equals(key)) {
					typedQuery.setParameter("PRODUCTBRANDUUID",
							productSearchDTO.getProductBrandUuid());
				} else if (ProductSearchDTO.KEY_HOT.equals(key)) {
					typedQuery.setParameter("ISHOT",
							productSearchDTO.isHot());
				} else if (ProductSearchDTO.KEY_NEW.equals(key)) {
					typedQuery.setParameter("ISNEW",productSearchDTO.isNew());
				} else if (ProductSearchDTO.KEY_RECOMMEND.equals(key)) {
					typedQuery.setParameter("ISRECOMMEND",productSearchDTO.isRecommend());
				} else if (ProductSearchDTO.KEY_ON_SALE.equals(key)) {
					typedQuery.setParameter("ISONSALE",productSearchDTO.isOnSale());
				} else if (ProductSearchDTO.KEY_INVENTORY.equals(key)) {
					typedQuery.setParameter("INVENTORY",productSearchDTO.getInventory());
				} else if (ProductSearchDTO.KEY_UNIT_POINT.equals(key)) {
					typedQuery.setParameter("UNITPOINTSTART",productSearchDTO.getUnitPointStart());
					typedQuery.setParameter("UNITPOINTEND",productSearchDTO.getUnitPointEnd());
				} else if (ProductSearchDTO.KEY_CATE_NAME.equals(key)) {
					typedQuery.setParameter("CATENAME",productSearchDTO.getCateName());
				} else if (ProductSearchDTO.KEY_GROUP_BUY_DEF.equals(key)) {
					typedQuery.setParameter("GROUPBUYDEFUUID",productSearchDTO.getGroupBuyDefUuid());
				}
			}
			productEntityList = typedQuery
					.setParameter("isDeleted", Boolean.FALSE)
					.setFirstResult(productSearchDTO.getStartIndex()).setMaxResults(productSearchDTO.getPageSize())
					.getResultList();
		} catch (NoResultException e) {
			logger.info("No record found for product");
		}
		return productEntityList;

	}


	@Override
	public int searchGroupBuyProductTotal(ProductSearchDTO productSearchDTO) throws DAOException {

		Long total = null;
		String query = "select count(*) from GroupBuyProductEntity b where b.isDeleted=:isDeleted";
		String[] keyArray = productSearchDTO.getKeyArray();
		for (int i = 0; i < keyArray.length; i++) {
			String key = keyArray[i];
			if (ProductSearchDTO.KEY_PRODUCT_NAME.equals(key)) {
				query = query + " and b.productEntity.productName like :PRODUCTNAME";
			} else if (ProductSearchDTO.KEY_MERCHANT.equals(key)) {
				query = query + " and b.productEntity.merchantEntity.merchantUuid = :MERCHANTUUID";
			} else if (ProductSearchDTO.KEY_PRODUCT_CATE.equals(key)) {
				query = query + " and (b.productEntity.productCateEntity.productCateUuid = :PRODUCTCATEUUID or b.productEntity.productCateEntity.parentCateEntity.productCateUuid = :PRODUCTCATEUUID)";
			} else if (ProductSearchDTO.KEY_SUPPLIER.equals(key)) {
				query = query + " and b.productEntity.supplierEntity.supplierUuid = :SUPPLIERUUID";
			} else if (ProductSearchDTO.KEY_BRAND.equals(key)) {
				query = query + " and b.productEntity.productBrandEntity.productBrandUuid = :PRODUCTBRANDUUID";
			} else if (ProductSearchDTO.KEY_HOT.equals(key)) {
				query = query + " and b.productEntity.isHot = :ISHOT";
			} else if (ProductSearchDTO.KEY_NEW.equals(key)) {
				query = query + " and b.productEntity.isNew = :ISNEW";
			} else if (ProductSearchDTO.KEY_RECOMMEND.equals(key)) {
				query = query + " and b.productEntity.isRecommend = :ISRECOMMEND";
			} else if (ProductSearchDTO.KEY_ON_SALE.equals(key)) {
				query = query + " and b.productEntity.isOnSale = :ISONSALE";
			} else if (ProductSearchDTO.KEY_INVENTORY.equals(key)) {
				query = query + " and b.productEntity.totalUnit <= :INVENTORY";
			} else if (ProductSearchDTO.KEY_UNIT_POINT.equals(key)) {
				query = query + " and b.productEntity.unitPoint >= :UNITPOINTSTART";
				query = query + " and b.productEntity.unitPoint <= :UNITPOINTEND";
			} else if (ProductSearchDTO.KEY_CATE_NAME.equals(key)) {
				query = query + " and b.productEntity.productCateEntity.cateName = :CATENAME" ;
			} else if (ProductSearchDTO.KEY_GROUP_BUY_DEF.equals(key)) {
				query = query + " and b.groupBuyDefEntity.groupBuyDefUuid = :GROUPBUYDEFUUID";
			} else if (ProductSearchDTO.KEY_GROUP_BUY_STATUS_BEING.equals(key)) {
				query = query + " and b.groupBuyDefEntity.status = '1' and b.groupBuyDefEntity.startTime < CURRENT_TIME() and b.groupBuyDefEntity.endTime > CURRENT_TIME()";
			} else if (ProductSearchDTO.KEY_GROUP_BUY_STATUS_COMPLETED.equals(key)) {
				query = query + " and b.groupBuyDefEntity.status = '1' and b.groupBuyDefEntity.endTime < CURRENT_TIME()";
			} else if (ProductSearchDTO.KEY_GROUP_BUY_STATUS_NOT_STARTED.equals(key)) {
				query = query + " and b.groupBuyDefEntity.status = '1' and b.groupBuyDefEntity.startTime > CURRENT_TIME()";
			} else if (ProductSearchDTO.KEY_GROUP_BUY_STATUS_NOT_COMPLETED.equals(key)) {
				query = query + " and b.groupBuyDefEntity.status = '1' and b.groupBuyDefEntity.endTime > CURRENT_TIME()";
			}
		}
		 query = query + " order by b.createDate desc";
		try {
			TypedQuery typedQuery = em.createQuery(query, Long.class);
			for (int i = 0; i < keyArray.length; i++) {
				String key = keyArray[i];
				if (ProductSearchDTO.KEY_PRODUCT_NAME.equals(key)) {
					typedQuery.setParameter("PRODUCTNAME",
							"%" + productSearchDTO.getProductName() + "%");
				} else if (ProductSearchDTO.KEY_MERCHANT.equals(key)) {
					typedQuery.setParameter("MERCHANTUUID",
							productSearchDTO.getMerchantUuid());
				} else if (ProductSearchDTO.KEY_PRODUCT_CATE.equals(key)) {
					typedQuery.setParameter("PRODUCTCATEUUID",
							productSearchDTO.getProductCateUuid());
				} else if (ProductSearchDTO.KEY_SUPPLIER.equals(key)) {
					typedQuery.setParameter("SUPPLIERUUID",
							productSearchDTO.getSupplierUuid());
				} else if (ProductSearchDTO.KEY_BRAND.equals(key)) {
					typedQuery.setParameter("PRODUCTBRANDUUID",
							productSearchDTO.getProductBrandUuid());
				} else if (ProductSearchDTO.KEY_HOT.equals(key)) {
					typedQuery.setParameter("ISHOT",
							productSearchDTO.isHot());
				} else if (ProductSearchDTO.KEY_NEW.equals(key)) {
					typedQuery.setParameter("ISNEW",productSearchDTO.isNew());
				} else if (ProductSearchDTO.KEY_RECOMMEND.equals(key)) {
					typedQuery.setParameter("ISRECOMMEND",productSearchDTO.isRecommend());
				} else if (ProductSearchDTO.KEY_ON_SALE.equals(key)) {
					typedQuery.setParameter("ISONSALE",productSearchDTO.isOnSale());
				} else if (ProductSearchDTO.KEY_INVENTORY.equals(key)) {
					typedQuery.setParameter("INVENTORY",productSearchDTO.getInventory());
				} else if (ProductSearchDTO.KEY_UNIT_POINT.equals(key)) {
					typedQuery.setParameter("UNITPOINTSTART",productSearchDTO.getUnitPointStart());
					typedQuery.setParameter("UNITPOINTEND",productSearchDTO.getUnitPointEnd());
				} else if (ProductSearchDTO.KEY_CATE_NAME.equals(key)) {
					typedQuery.setParameter("CATENAME",productSearchDTO.getCateName());
				} else if (ProductSearchDTO.KEY_GROUP_BUY_DEF.equals(key)) {
					typedQuery.setParameter("GROUPBUYDEFUUID",productSearchDTO.getGroupBuyDefUuid());
				}
			}
			total = (Long) typedQuery
					.setParameter("isDeleted", Boolean.FALSE)
					.getSingleResult();
		} catch (NoResultException e) {
			logger.info("No record found for product");
		}
		return total == null?0:total.intValue();

	}
}
